//
//  BTEServerTool.swift
//  BTE
//
//  Created by Mike Zhang on 2025/8/6.
//

import UIKit
import Alamofire
import SmartCodable


class hostmodels: SmartCodable {
    var stan: String?
    required init(){}
}



class BTEServiceTool<T: SERVER_NET_TYPE>: NSObject {

   var netConnected: Bool {
       return NetworkReachabilityManager()?.isReachable ?? false
   }

   let sessionHandle: Session = {
       let config = URLSessionConfiguration.default
       config.timeoutIntervalForRequest = 3.0      // 单个请求超时
       return Session(configuration: config)
   }()
   
   override init() {
       super.init()
   }
   
   func buildParams(task: SERVER_TASK) -> ([String: Any], ParameterEncoding){
       switch task {
       case .requestPlain:
           return ([:], URLEncoding.default)
       case .requestParameters(parameters: let parameters, encoding: let encoding):
           return (parameters, encoding)
       }
   }

   
   func deserialize<M:ServerBaseModelProtocol>(with result:AFDataResponse<Data>,target: T,handle: @escaping (RsultModel<M>) -> Void){

       guard let response = try? result.result.get() else {
           handle(.failure(.unknow))
           return
       }
       
       guard let dict = try? JSONSerialization.jsonObject(with: response, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any] else {
           handle(.failure(.unknow))
           return
       }
       
       print(dict)
       
       if let model = M.deserialize(from: dict) {
           
           if model.geothermally != 0 {
               
               handle(.failure(.Error(c: model.geothermally, m: model.squushy)))
               return
           }
           
           handle(.success(model))
       }
       
   }
    
   
   
   func fetchData<M: ServerBaseModelProtocol>(target: T, resultClass: M.Type, handle: @escaping (RsultModel<M>) -> Void){
       guard netConnected else {
           handle(.failure(.unknow))
           return
       }
       
       let method = Alamofire.HTTPMethod(rawValue: target.METHOD.rawValue)
       
       let headers = Alamofire.HTTPHeaders(target.HEADER ?? [:])

       let params = buildParams(task: target.TASK)
 
       let url = target.ROOT + target.PATH
       
       let f = url.URL_Pre()
       
       sessionHandle.request(f?.absoluteString ?? "",
                              method: method,
                              parameters: params.0,
                              encoding: params.1,
                              headers: headers)
           .validate(statusCode: 200..<500)
           .cURLDescription { kd in
               print(kd)
           }
           .responseData {[weak self] result in
               guard let _weakSelf = self else {
                   return
               }
               switch result.result {
               case .success:
                   _weakSelf.deserialize(with: result, target: target) { model in
                       handle(model)
                   }
                   break
               case .failure(let m):
                   print(m)
                   handle(.failure(.Error(c: m.responseCode ?? 0, m: m.localizedDescription)))
               }
           }
   }
   
    
    func uploadPic<M: ServerBaseModelProtocol>(target: T, resultClass: M.Type, handle: @escaping (RsultModel<M>) -> Void ){
        
        guard netConnected else {
            handle(.failure(.unknow))
            return
        }
        
        let method = Alamofire.HTTPMethod(rawValue: target.METHOD.rawValue)
        
        let headers = Alamofire.HTTPHeaders(target.HEADER ?? [:])

        let params = buildParams(task: target.TASK)
  
        let url = target.ROOT + target.PATH
        
        let f = url.URL_Pre()
        
 
        sessionHandle.upload(multipartFormData: { multipartFormData in
            
            if let image = params.0["uncondoled"] as? Data {
                multipartFormData.append(image, withName: "uncondoled", fileName: "\(arc4random()).png", mimeType: MIMEType.image.rawValue)
            }
            
            if let a = params.0["dikegrave"] as? String {
                multipartFormData.append(Data(a.utf8), withName: "dikegrave")
            }
            
            if let b = params.0["reincorporation"] as? String {
                multipartFormData.append(Data(b.utf8), withName: "reincorporation")
            }
            
        }, to: f!.absoluteString, usingThreshold: UInt64(), method: method, headers: headers, interceptor: nil, fileManager: FileManager(), requestModifier: nil)
            .validate(statusCode: 200..<500)
            .cURLDescription { kd in
                print(kd)
            }
            .uploadProgress { pro in
               print("\(Int(pro.fractionCompleted * 100))%")
            }
            .responseData { [weak self] result in
                guard let _weakSelf = self else {
                    return
                }
                switch result.result {
                case .success:
                    _weakSelf.deserialize(with: result, target: target) { model in
                        handle(model)
                    }
                    break
                case .failure(let error):
                    return handle(.failure(.Error(c: error.responseCode ?? 0, m: error.localizedDescription)))
                }
            }
    }
    
    
    func getsomejsonhost<M: ServerBaseModelProtocol>(target: T, responseClass: M.Type, completion: @escaping (RsultModel<M>) -> Void) {
        let fileManager = FileManager.default
        let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let fileURL = documentsURL.appendingPathComponent("hosturl")
        
        if fileManager.fileExists(atPath: fileURL.path) {
            do {
                try fileManager.removeItem(at: fileURL)
            } catch {
                completion(.failure(.unknow))
                return
            }
        }
        
        let destination: DownloadRequest.Destination = { _, _ in
            return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
        }
        
        let method = Alamofire.HTTPMethod(rawValue: target.METHOD.rawValue)
 
        AF.download("https://id3-dc.oss-ap-southeast-5.aliyuncs.com/pinjaman-instan/stan.json", to: destination).response { response in
            switch response.result {
            case .success(let fileURL):
                do {
                    let fileData = try Data(contentsOf: fileURL!)
                    if let jsonString = String(data: fileData, encoding: .utf8) {
                        let datas = [hostmodels].deserialize(from: jsonString)
                        let mode = NetBaseModel<[hostmodels]>()
                        mode.sidelingwise = datas
                        completion(.success(mode as? M))
                    } else {
                        completion(.failure(.unknow))
                    }
                } catch {
                    completion(.failure(.unknow))
                }
            case .failure(let error):
                completion(.failure(.unknow))
            }
        }
    }
}


